package com.tcp2.net;

/**
 * Author: 杨俊辉
 * Time: 2014-09-22 17:34
 * Copyright (C) 2014 Xiamen Yaxon Networks CO.,LTD.
 */

import com.tcp2.handler.BaseMsgHandler;
import com.tcp2.server.ProtoConstants;
import com.tcp2.server.ProtoMsg;
import com.tcp2.util.ConfigUtil;
import com.tcp2.util.Md5Util;
import com.tcp2.util.ProtoUtil;
import com.yaxon.vndp.common.util.CodecUtils;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.ConcurrentMap;

import static com.tcp2.server.ProtoConstants.*;


/**
 * 链路管理处理类
 */

@Service
public class LinkHandler extends BaseMsgHandler {

    protected static Logger logger = LoggerFactory.getLogger(LinkHandler.class);




    /**
     * 809协议处理
     */
    @Override
    public void handle(ProtoMsg msg)  {
        switch (msg.msgId) {
            case UP_CONNECT_REQ:
                doUpConnectReq(msg);
                break;
            case UP_DISCONNECT_REQ:
                doUpDisconnectReq(msg);
                break;
            case UP_LINKTEST_REQ:
                doUpLinkTestReq(msg);
                break;
            case UP_DISCONNECT_INFORM:
                doUpDisconnectInform(msg);
                break;
            case UP_CLOSELINK_INFORM:
                doUpCloseLinkInform(msg);
                break;
            default:
                throw new RuntimeException("未知消息类型：0x" + CodecUtils.shortToHex((short) msg.msgId));

        }
    }

    private void doUpConnectReq(ProtoMsg msg) {

        logger.info("-> 收到主链路登录请求，消息id：0x{}，下级平台接入码：{}",  CodecUtils.shortToHex((short) msg.msgId), msg.gnssCenterId);
        ConcurrentMap<Integer, PlatformChannel> plat2channelMap = PlatformMap.getPlat2channelMap();
        PlatformChannel platformChannel = plat2channelMap.get(msg.gnssCenterId);
       // System.out.println("platformChannel-object=" + platformChannel);


        ByteBuf buf = msg.msgData;
        Integer userId = buf.readInt();
        String password = ProtoUtil.readOctetString(buf, 8);
        String downLinkIp = ProtoUtil.readOctetString(buf, 32);
        Integer downLinkPort = buf.readUnsignedShort();


        String link_gnssCenterId= ConfigUtil.getFileIO("link.gnssCenterId","app.properties");
        String link_username=ConfigUtil.getFileIO("link.username","app.properties");
        String link_pwd=ConfigUtil.getFileIO("link.pwd","app.properties");
        String link_ip=ConfigUtil.getFileIO("link.ip","app.properties");
        System.out.println(password);
        byte rc = 0x00;
            if (!downLinkIp.equals(link_ip)) {
                rc = 0x01;
                logger.info("IP 地址不正确");
            } else if (!link_gnssCenterId.equals(msg.gnssCenterId+"")) {
                rc = 0x02;
                logger.info("接入码不正确");
            }

            else if (!link_pwd.equals(password)) { //数据库用md5加密截取前8位，
                rc = 0x04;
                logger.info("密码错误");
            } else if (platformChannel.getConnectState() != 0) {
                rc = 0x05;
                logger.info("资源紧张，稍后再连接（已经占用）");

            }
        /* else {
                rc = 0x03;
                logger.info(" 用户没有注册");
            }*/


        ProtoMsg out = new ProtoMsg();
        out.msgId = ProtoConstants.UP_CONNECT_RSP;
        ByteBuf resData = Unpooled.buffer(1);
        resData.writeByte(rc);
        resData.writeBytes(new byte[4]);
        out.msgData = resData;

        ConcurrentMap<Integer, MasterLinkHandler> plat2GovMap = PlatformMap.getPlat2govMap();
        MasterLinkHandler masterLinkHandler = plat2GovMap.get(msg.gnssCenterId);
        ChannelFuture cf = masterLinkHandler.sendMessage(platformChannel.getChannel(), out);

        try {
            cf.sync();
        } catch (InterruptedException e) {
            logger.warn("发送主链路请求应答失败", e);
            rc = 0x06;
        }

        if (rc == 0x00) { //验证成功
            logger.info("主链路登录请求处理成功", rc);
            platformChannel.connnected();

            //获取接入的上级平台


            //更新接入平台上线状态
            try {

            } catch (Exception e) {
                logger.error("更新接入平台上线状态失败", e);
            }




            //保存链路通断上线记录


            //上级平台连接下级平台实现从链路服务
            try {
                SlaveLink slaveLink = new SlaveLink();
                slaveLink.setGnssCenterId(msg.gnssCenterId);
                slaveLink.setDownLinkIp(downLinkIp);
                slaveLink.setDownLinkPort(downLinkPort);
                slaveLink.setVerifyCode(0);
                slaveLink.setDxsConfig(masterLinkHandler.getDxsConfig());
                slaveLink.setMessageDispatcher(masterLinkHandler.getMessageDispatcher());
                slaveLink.start();
                ConcurrentMap<Integer, SlaveLink> gov2platMap = PlatformMap.getGov2platMap();
                gov2platMap.put(msg.gnssCenterId, slaveLink);


            } catch (Throwable e) {
                logger.error("从链路启动失败", e);
            }
        } else {
            platformChannel.disconnected(platformChannel.getChannel());
            plat2channelMap.remove(platformChannel);
        }


    }

    private void doUpDisconnectReq(ProtoMsg msg) {
        logger.info("-> 收到主链路注销请求，消息id：0x{}，下级平台接入码：{}",  CodecUtils.shortToHex((short) msg.msgId), msg.gnssCenterId);
        ConcurrentMap<Integer, PlatformChannel> plat2channelMap = PlatformMap.getPlat2channelMap();
        PlatformChannel platformChannel = plat2channelMap.get(msg.gnssCenterId);
        System.out.println("platformChannel-object:" + platformChannel);
        ConcurrentMap<Integer, MasterLinkHandler> plat2GovMap = PlatformMap.getPlat2govMap();
        MasterLinkHandler masterLinkHandler = plat2GovMap.get(msg.gnssCenterId);

        byte rc = 0;
        ProtoMsg out = new ProtoMsg();
        out.msgId = ProtoConstants.UP_DISCONNECT_RSP;
        out.msgData = Unpooled.buffer(0);
        ChannelFuture cf =  masterLinkHandler.sendMessage(platformChannel.getChannel(), out);
        try {
            cf.sync();
        } catch (InterruptedException e) {
            logger.warn("发送主链路注销应答失败", e);
            rc = 1;
        }
        if(rc == 0) {
            cf.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture cf) throws Exception {
                    cf.channel().close();
                }
            });

        }


    }

    private void doUpLinkTestReq(ProtoMsg msg) {
        logger.info("-> 收到主链路连接保持请求，消息id：{}，下级平台接入码：{}", msg.msgId, msg.gnssCenterId);

        ConcurrentMap<Integer, PlatformChannel> plat2channelMap = PlatformMap.getPlat2channelMap();
        PlatformChannel platformChannel = plat2channelMap.get(msg.gnssCenterId);
        System.out.println("platformChannel-object:" + platformChannel);
        ConcurrentMap<Integer, MasterLinkHandler> plat2GovMap = PlatformMap.getPlat2govMap();
        MasterLinkHandler masterLinkHandler = plat2GovMap.get(msg.gnssCenterId);

        ProtoMsg out = new ProtoMsg();
        out.msgId = ProtoConstants.UP_LINKTEST_RSP;
        out.msgData = Unpooled.buffer(0);

        masterLinkHandler.sendMessage(platformChannel.getChannel(), out);
        platformChannel.checkAlive();
    }

    private void doUpDisconnectInform(ProtoMsg msg) {
        logger.info("-> 收到主链路断开通知消息，消息id：0x{}，下级平台接入码：{}",  CodecUtils.shortToHex((short) msg.msgId), msg.gnssCenterId);


    }

    private void doUpCloseLinkInform(ProtoMsg msg) {
        logger.info("-> 收到下级平台主动关闭链路通知，消息id：0x{}，下级平台接入码：{}",  CodecUtils.shortToHex((short) msg.msgId), msg.gnssCenterId);


        ConcurrentMap<Integer, PlatformChannel> platformMap = PlatformMap.getPlat2channelMap();
        PlatformChannel platformChannel =  platformMap.get(msg.gnssCenterId);
        if(platformChannel !=null) {
            platformChannel.getChannel().close();
        }
        ConcurrentMap<Integer, SlaveLink> gov2platMap = PlatformMap.getGov2platMap();
        SlaveLink slaveLink = gov2platMap.get(msg.gnssCenterId);
        if(slaveLink != null){
            slaveLink.stop();
        }

    }

}
